package com.example.agent;

import java.lang.instrument.Instrumentation;
import java.util.concurrent.atomic.AtomicInteger;

import com.example.advice.ConstructorAdvice;
import com.example.interfaces.Operation;
import com.example.listener.TransformListener;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.matcher.ElementMatchers;

/**
 * https://juejin.cn/post/6917570505365012488
 * 
 * @author simple
 *
 */
public class AgentPremain {

	public static void premain(String arguments, Instrumentation instrumentation) {

		System.out.println("Agent premain!");
		new AgentBuilder.Default()
				// 限定作用范围，为接口Operation的实现类
				.type(ElementMatchers.hasSuperType(ElementMatchers.namedOneOf(Operation.class.getName()))
						.and(ElementMatchers.not(ElementMatchers.isInterface())))
				.transform((builder, typeDescription, classLoader, module) -> builder
						// 定义类成员变量，命名counter，类型AtomicInteger，作用域public
						.defineField("counter", AtomicInteger.class, Visibility.PUBLIC)
						// 确定切点为所有构造函数，紧跟这使用.intercept(...)进行通知织入
						.constructor(ElementMatchers.any())
						// 通知织入上面的切点
						.intercept(Advice.to(ConstructorAdvice.class)))
				.with(new TransformListener()).installOn(instrumentation);
	}
}
